﻿using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;

namespace Zocono.WCS.Infrastructure.BaseRepository.SqlSugarUtil
{
    public static class SqlSugarExtend
    {
        #region 扩展事务，发生死锁后再次尝试执行

        /// <summary>
        /// 扩展SqlSugar事务方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="context"></param>
        /// <param name="func"></param>
        /// <param name="retryTimer"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static async Task<SqlSugarTranResultDto<T>> ExecTranAsync<T>(this ISqlSugarClient sqlSugarClient, Func<Task<T>> func, int retryTimer = 1)
        {
            int c = 0;
            retryTimer = (retryTimer > 3 ? 3 : retryTimer);
            List<SqlSugarTranResultDto<T>> dbResults = new List<SqlSugarTranResultDto<T>>();
            var logUtil = ServiceCollectionExt.serviceProvider.GetService<ILogUtil>();
            while (true)
            {
                c++;
                var dbResult = await ExecTranAsync(sqlSugarClient, func);
                dbResults.Add(dbResult);
                if (dbResult.IsSuccess)
                {
                    break;
                }
                else
                {
                    logUtil.Error($"第{c}次执行数据库事务，发生异常:{dbResult.ErrorException}");
                }
                if (c < retryTimer)
                {
                    Thread.Sleep(100);
                }
                else
                {
                    break;
                }

            }
            SqlSugarTranResultDto<T> result = dbResults.Last();
            var fails = dbResults.Where(m => !m.IsSuccess).Select(m => m.ErrorMessage).ToList();
            result.IsSuccess = dbResults.Any(m => m.IsSuccess);
            result.FailCount = fails.Count;
            if (result.IsSuccess)
            {
                if (result.FailCount > 0)
                {
                    result.ErrorMessage = $"事务执行成功，但曾发生过异常:{string.Join(',', fails)}";
                }
                else
                {
                    result.ErrorMessage = $"事务执行成功";
                }
            }
            else
            {
                throw new Exception($"事务执行异常:{string.Join(',', fails)}");
            }
            return result;
        }
        private static async Task<SqlSugarTranResultDto<T>> ExecTranAsync<T>(this ISqlSugarClient sqlSugarClient, Func<Task<T>> func)
        {
            SqlSugarTranResultDto<T> resultDto = new SqlSugarTranResultDto<T>();
            SqlSugarClient context = sqlSugarClient as SqlSugarClient;
            try
            {
                context.BeginTran();
                resultDto.Data = await func();
                context.CommitTran();
                resultDto.IsSuccess = true;
            }
            catch (Exception ex)
            {
                resultDto.ErrorException = ex;
                resultDto.ErrorMessage = ex.Message;
                resultDto.IsSuccess = false;
                context.RollbackTran();
            }

            return resultDto;
        }


        #endregion

    }
    public class SqlSugarTranResultDto<T> : DbResult<T>
    {
        /// <summary>
        /// 事务失败次数
        /// </summary>
        public int FailCount { get; set; } = 0;
    }
}
